/*
针对 AES 128, 有限域 GF(2^8)上的运算，AES S 盒的生成，列混淆需要
对外只开放 byte 类型
 */
package GF

import (
	"math"
)

// 有限域加
func Plus(p1 byte, p2 byte) byte {
	return p1 ^ p2
}

func Minus(m1 byte, m2 byte) byte {
	return m1 ^ m2
}

// 有限域上乘
func Multiply(m1 byte, m2 byte) byte {
	return byte(multiply(int(m1), int(m2)))
}

func multiply(m1 int, m2 int) int {
	re := 0
	for i := 0; i < 8; i++ {
		last := (m1 >> i) & 0x1
		if last == 1 {
			re = re ^ m2
		}
		if (m2 >> 7) & 0x1 == 0 {
			m2 = m2 << 1
		} else {
			m2 = (m2 << 1) ^ 27
		}
	}
	return re
}

/*
次函数注意限制条件
有限域上除 默认 d1 > d2, d2 != 0 注意d1, d2 位数都不大于8
返回商和余数
 */
func Divide(d1 byte, d2 byte) (byte, byte) {
	re1, re2 := divide(int(d1), int(d2))
	return byte(re1), byte(re2)
}

func divide(d1 int, d2 int) (int, int) {
	sh := 0
	if d1 == d2 {
		return 1, 0
	}
	for d1 >= d2 {
		tmp := d2
		f1 := getFirst(d1)
		f2 := getFirst(d2)
		tmp = tmp << (f1 - f2)
		sh += int(math.Pow(float64(2), float64(f1 - f2)))
		d1 = tmp ^ d1
	}
	return sh, d1
}

// 获取 n 的二进制位数
func getFirst(n int) int {
	count := 0
	for n > 1 {
		count ++
		n /= 2
	}
	return count
}

// 关于 x^8 + x^4 + x^3 + x + 1 的逆
func Inverse(m1 byte) byte {
	if m1 == 0 {
		return 0
	}
	return byte(inverse(int(m1)))
}

func inverse(m int) int {
	n := 283
	u1, u2 := 1, 0
	v1, v2 := 0, 1
	for m != 1 {
		r, yu := divide(n, m)
		tmp1, tmp2 := u2, v2
		u2 = u1 ^ multiply(r, u2)
		v2 = v1 ^ multiply(r, v2)
		u1 = tmp1
		v1 = tmp2
		n = m
		m = yu
	}
	return v2
}
